home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libc / crt0 / c1args.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-28  |  9.0 KB  |  403 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <libc/stubs.h>
  3. #include <io.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <crt0.h>
  7. #include <go32.h>
  8. #include <fcntl.h>
  9. #include <libc/farptrgs.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12. #include <stubinfo.h>
  13.  
  14. #define ds _my_ds()
  15.  
  16. static void *
  17. c1xmalloc(size_t s)
  18. {
  19.   void *q = malloc(s);
  20.   if (q == 0)
  21.   {
  22. #define err(x) _write(STDERR_FILENO, x, sizeof(x)-1)
  23.     err("No memory to gather arguments\r\n");
  24.     _exit(1);
  25.   }
  26.   return q;
  27. }
  28.  
  29. static int
  30. far_strlen(int selector, int linear_addr)
  31. {
  32.   int save=linear_addr;
  33.   _farsetsel(selector);
  34.   while (_farnspeekb(linear_addr))
  35.     linear_addr++;
  36.   return linear_addr - save;
  37. }
  38.  
  39. static int
  40. atohex(char *s)
  41. {
  42.   int rv = 0;
  43.   while (*s)
  44.   {
  45.     int v = *s - '0';
  46.     if (v > 9)
  47.       v -= 7;
  48.     v &= 15; /* in case it's lower case */
  49.     rv = rv*16 + v;
  50.     s++;
  51.   }
  52.   return rv;
  53. }
  54.  
  55. typedef struct Arg {
  56.   char *arg;
  57.   char **arg_globbed;
  58.   struct ArgList *arg_file;
  59.   struct Arg *next;
  60.   int was_quoted;
  61. } Arg;
  62.  
  63. typedef struct ArgList {
  64.   int argc;
  65.   Arg **argv;
  66. } ArgList;
  67.  
  68. static Arg *new_arg(void)
  69. {
  70.   Arg *a = (Arg *)c1xmalloc(sizeof(Arg));
  71.   memset(a, 0, sizeof(Arg));
  72.   return a;
  73. }
  74.  
  75. static void delete_arglist(ArgList *al);
  76.  
  77. static void
  78. delete_arg(Arg *a)
  79. {
  80.   if (a->arg) free(a->arg);
  81.   if (a->arg_globbed)
  82.   {
  83.     int i;
  84.     for (i=0; a->arg_globbed[i]; i++)
  85.       free(a->arg_globbed[i]);
  86.     free(a->arg_globbed);
  87.   }
  88.   if (a->arg_file)
  89.     delete_arglist(a->arg_file);
  90.   free(a);
  91. }
  92.  
  93. static ArgList *
  94. new_arglist(int count)
  95. {
  96.   ArgList *al = (ArgList *)c1xmalloc(sizeof(ArgList));
  97.   al->argc = count;
  98.   al->argv = (Arg **)c1xmalloc((count+1)*sizeof(Arg *));
  99.   memset(al->argv, 0, (count+1)*sizeof(Arg *));
  100.   return al;
  101. }
  102.  
  103. static void
  104. delete_arglist(ArgList *al)
  105. {
  106.   int i;
  107.   for (i=0; i<al->argc; i++)
  108.     delete_arg(al->argv[i]);
  109.   free(al->argv);
  110.   free(al);
  111. }
  112.  
  113. static ArgList *
  114. parse_bytes(char *bytes, int length)
  115. {
  116.   int largc, quote=0, i;
  117.   Arg *a, **anext, *afirst;
  118.   ArgList *al;
  119.   char *bp=bytes, *ep, *epp, *last=bytes+length;
  120.  
  121.   anext = &afirst;
  122.   largc = 0;
  123.   while (bp<last)
  124.   {
  125.     while (isspace(*bp) && bp < last)
  126.       bp++;
  127.     if (bp == last)
  128.       break;
  129.     ep = epp = bp;
  130.     *anext = a = new_arg();
  131.     while ((quote || !isspace(*ep)) && ep < last)
  132.     {
  133.       if (quote && *ep == quote)
  134.       {
  135.         quote = 0;
  136.         ep++;
  137.       }
  138.       else if (!quote && (*ep == '\'' || *ep == '"'))
  139.       {
  140.         quote = *ep;
  141.         ep++;
  142.         a->was_quoted = 1;
  143.       }
  144.       else if (*ep == '\\' && strchr("'\"", ep[1]) && ep < last-1)
  145.       {
  146.         ep++;
  147.         *epp++ = *ep++;
  148.         a->was_quoted = 1;
  149.       }
  150.       else
  151.       {
  152.         *epp++ = *ep++;
  153.       }
  154.     }
  155.     anext = &(a->next);
  156.     largc++;
  157.     a->arg = (char *)c1xmalloc(epp-bp+1);
  158.     memcpy(a->arg, bp, epp-bp);
  159.     a->arg[epp-bp] = 0;
  160.     bp = ep+1;
  161.   }
  162.   al = new_arglist(largc);
  163.   for (i=0, a=afirst; i<largc; i++, a=a->next)
  164.     al->argv[i] = a;
  165.   return al;
  166. }
  167.  
  168. static int
  169. count_args(ArgList *al)
  170. {
  171.   int i, r=0;
  172.   for (i=0; i<al->argc; i++)
  173.   {
  174.     int j;
  175.     if (al->argv[i]->arg_globbed)
  176.     {
  177.       for (j=0; al->argv[i]->arg_globbed[j]; j++);
  178.       r += j;
  179.     }
  180.     else if (al->argv[i]->arg_file)
  181.     {
  182.       r += count_args(al->argv[i]->arg_file);
  183.     }
  184.     else
  185.     {
  186.       r++;
  187.     }
  188.   }
  189.   return r;
  190. }
  191.  
  192. static char **
  193. fill_args(char **largv, ArgList *al)
  194. {
  195.   int i;
  196.   for (i=0; i<al->argc; i++)
  197.   {
  198.     int j;
  199.     if (al->argv[i]->arg_globbed)
  200.     {
  201.       for (j=0; al->argv[i]->arg_globbed[j]; j++)
  202.       {
  203.         *largv++ = al->argv[i]->arg_globbed[j];
  204.         al->argv[i]->arg_globbed[j] = 0;
  205.       }
  206.     }
  207.     else if (al->argv[i]->arg_file)
  208.     {
  209.       largv = fill_args(largv, al->argv[i]->arg_file);
  210.     }
  211.     else
  212.     {
  213.       *largv++ = al->argv[i]->arg;
  214.       al->argv[i]->arg = 0;
  215.     }
  216.   }
  217.   return largv;
  218. }
  219.  
  220. static void
  221. expand_response_files(ArgList *al)
  222. {
  223.   int i, f;
  224.   for (i=0; i<al->argc; i++)
  225.   {
  226.     if (! al->argv[i]->was_quoted && al->argv[i]->arg[0] == '@')
  227.       if ((f = _open(al->argv[i]->arg+1, O_RDONLY)) >= 0)
  228.       {
  229.     char *bytes;
  230.     int len, st_size;
  231.     st_size = lseek(f, 0L, SEEK_END);
  232.     lseek(f, 0L, SEEK_SET);
  233.         bytes = (char *)alloca(st_size);
  234.         len = _read(f, bytes, st_size);
  235.         _close(f);
  236.         al->argv[i]->arg_file = parse_bytes(bytes, len);
  237.         expand_response_files(al->argv[i]->arg_file);
  238.       }
  239.   }
  240. }
  241.  
  242. static void
  243. expand_wildcards(ArgList *al)
  244. {
  245.   int i;
  246.   for (i=0; i<al->argc; i++)
  247.   {
  248.     if (al->argv[i]->arg_file)
  249.       expand_wildcards(al->argv[i]->arg_file);
  250.     else if (!(al->argv[i]->was_quoted))
  251.     {
  252.       al->argv[i]->arg_globbed = __crt0_glob_function(al->argv[i]->arg);
  253.     }
  254.   }
  255. }
  256.  
  257. void
  258. __crt0_setup_arguments(void)
  259. {
  260.   ArgList *arglist;
  261.   char *argv0;
  262.   int prepend_argv0 = 1;
  263.  
  264.   /*
  265.   ** first, figure out what to pass for argv[0]
  266.   */
  267.   {
  268.     int i;
  269.     char *ap, *ls, *fc;
  270. /*    char newbase[14]; */
  271.     
  272.     if (_crt0_startup_flags & _CRT0_FLAG_DROP_DRIVE_SPECIFIER)
  273.       if (__dos_argv0[1] == ':')
  274.         __dos_argv0 += 2;
  275.  
  276.     ls = __dos_argv0;
  277.     for (ap=__dos_argv0; *ap; ap++)
  278.       if (*ap == ':' || *ap == '\\' || *ap == '/')
  279.         ls = ap + 1;
  280.     fc = ls;
  281. #if 0
  282.     /* We never do this!  Only the stub uses this field */
  283.     if (_stubinfo->basename[0])
  284.     {
  285.       for (i=0; i<8 && _stubinfo->basename[i]; i++)
  286.     newbase[i] = _stubinfo->basename[i];
  287.       newbase[i++] = '.';
  288.       newbase[i++] = 'E';
  289.       newbase[i++] = 'X';
  290.       newbase[i++] = 'E';
  291.       newbase[i++] = 0;
  292.       fc = newbase;
  293.     }
  294. #endif
  295.     if (_stubinfo->argv0[0])
  296.     {
  297.       fc = _stubinfo->argv0;
  298.     }
  299.     argv0 = (char *)calloc(1, ls-__dos_argv0+strlen(fc)+1);
  300.     if (ls == __dos_argv0)
  301.       strncpy(argv0, fc, 16);
  302.     else
  303.     {
  304.       strncpy(argv0, __dos_argv0, ls-__dos_argv0);
  305.       strncat(argv0, fc, 16);
  306.     }
  307.     for (i=0; (fc == _stubinfo->argv0)?(i<ls-__dos_argv0):(argv0[i]); i++)
  308.     {
  309.       if (!(_crt0_startup_flags & _CRT0_FLAG_USE_DOS_SLASHES))
  310.         if (argv0[i] == '\\')
  311.           argv0[i] = '/';
  312.       if (!(_crt0_startup_flags & _CRT0_FLAG_PRESERVE_UPPER_CASE))
  313.         if (isupper(argv0[i]))
  314.           argv0[i] = tolower(argv0[i]);
  315.     }
  316.     if (_crt0_startup_flags & _CRT0_FLAG_DROP_EXE_SUFFIX)
  317.     {
  318.       char *sp = argv0 + strlen(argv0) - 4;
  319.       if (sp[0] == '.'
  320.       && (sp[1] == 'e' || sp[1] == 'E')
  321.       && (sp[2] == 'x' || sp[2] == 'X')
  322.       && (sp[3] == 'e' || sp[3] == 'E'))
  323.         *sp = 0;
  324.     }
  325.   }
  326.   
  327.   /*
  328.   ** Next, scan dos's command line.
  329.   */
  330.   {
  331.     char doscmd[128];
  332.     movedata(_stubinfo->psp_selector, 128, ds, (int)doscmd, 128);
  333.     arglist = parse_bytes(doscmd+1, doscmd[0] & 0x7f);
  334.   }
  335.   
  336.   /*
  337.   ** Check for !proxy
  338.   */
  339.   if (arglist->argc > 3 && strcmp(arglist->argv[0]->arg, "!proxy") == 0)
  340.   {
  341.     int argv_seg, argv_ofs, i;
  342.     unsigned short *rm_argv;
  343.     __crt0_argc = atohex(arglist->argv[1]->arg);
  344.     argv_seg = atohex(arglist->argv[2]->arg);
  345.     argv_ofs = atohex(arglist->argv[3]->arg);
  346.     delete_arglist(arglist);
  347.  
  348.     rm_argv = (unsigned short *)alloca(__crt0_argc*sizeof(unsigned short));
  349.     movedata(_dos_ds, argv_seg*16+argv_ofs, ds, (int)rm_argv, __crt0_argc*sizeof(unsigned short));
  350.  
  351.     arglist = new_arglist(__crt0_argc);
  352.     
  353.     for (i=0; i<__crt0_argc; i++)
  354.     {
  355.       int al = far_strlen(_dos_ds, argv_seg*16 + rm_argv[i]);
  356.       arglist->argv[i] = new_arg();
  357.       arglist->argv[i]->arg = (char *)c1xmalloc(al+1);
  358.       movedata(_dos_ds, argv_seg*16 + rm_argv[i], ds, (int)(arglist->argv[i]->arg), al+1);
  359.     }
  360.     prepend_argv0 = 0;
  361.   }
  362.   else if (arglist->argc > 3 && strcmp(arglist->argv[0]->arg, "!proxy2") == 0)
  363.   {
  364.     int argv_sel, argv_ofs, i;
  365.     unsigned long *pm_argv;
  366.     __crt0_argc = atohex(arglist->argv[1]->arg);
  367.     argv_sel = atohex(arglist->argv[2]->arg);
  368.     argv_ofs = atohex(arglist->argv[3]->arg);
  369.     delete_arglist(arglist);
  370.  
  371.     pm_argv = (unsigned long *)alloca(__crt0_argc*sizeof(unsigned long));
  372.     movedata(argv_sel, argv_ofs, ds, (int)pm_argv, __crt0_argc*sizeof(unsigned long));
  373.  
  374.     arglist = new_arglist(__crt0_argc);
  375.     
  376.     for (i=0; i<__crt0_argc; i++)
  377.     {
  378.       int al = far_strlen(argv_sel, pm_argv[i]);
  379.       arglist->argv[i] = new_arg();
  380.       arglist->argv[i]->arg = (char *)c1xmalloc(al+1);
  381.       movedata(argv_sel, pm_argv[i], ds, (int)(arglist->argv[i]->arg), al+1);
  382.     }
  383.     prepend_argv0 = 0;
  384.   }
  385.  
  386.   /*
  387.   **  Now, expand response files
  388.   */
  389.   if (!(_crt0_startup_flags & _CRT0_FLAG_DISALLOW_RESPONSE_FILES))
  390.     expand_response_files(arglist);
  391.  
  392.   /*
  393.   **  Now, expand wildcards
  394.   */
  395.   expand_wildcards(arglist);
  396.  
  397.   __crt0_argc = prepend_argv0 + count_args(arglist);
  398.   __crt0_argv = (char **)c1xmalloc((__crt0_argc+1) * sizeof(char *));
  399.   if (prepend_argv0)
  400.     __crt0_argv[0] = argv0;
  401.   *fill_args(__crt0_argv+prepend_argv0, arglist) = 0;
  402. }
  403.